//--------------------------------------------------------------------------------------
// Texture sampler
//--------------------------------------------------------------------------------------

SamplerState samPoint
{
	Filter = MIN_MAG_MIP_POINT;
    AddressU = Clamp;
    AddressV = Clamp;
    AddressW = Clamp;
};

SamplerState samLinear
{
	Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Clamp;
    AddressV = Clamp;
    AddressW = Clamp;
};

struct VS_INPUT
{
    float4 pos		: POSITION0;
    float3 tex		: TEXCOORD0;
};

struct PS_INPUT
{
    float4 pos		: SV_POSITION;
    float3 tex		: TEXCOORD0;
};

struct TriData
{
	uint triInd;
	float depth;
};

//States

BlendState AlphaBlendDisable
{
   BlendEnable[0] = False;
};

BlendState SrcAlphaBlend
{
   BlendEnable[0]           = TRUE;
   SrcBlend                 = SRC_ALPHA;
   DestBlend                = INV_SRC_ALPHA;
   BlendOp                  = ADD;
   SrcBlendAlpha            = SRC_ALPHA;
   DestBlendAlpha           = INV_SRC_ALPHA;
   BlendOpAlpha             = ADD;
   RenderTargetWriteMask[0] = 0x0F;
};

BlendState BackToFrontAlphaBlend
{
   BlendEnable[0]           = TRUE;
   SrcBlend                 = INV_DEST_ALPHA;
   DestBlend                = ONE;
   BlendOp                  = ADD;
   SrcBlendAlpha            = INV_DEST_ALPHA;
   DestBlendAlpha           = ONE;
   BlendOpAlpha             = ADD;
   RenderTargetWriteMask[0] = 0x0F;
};

DepthStencilState DepthWrite
{
	DepthEnable = True;
    DepthFunc = Always;
    DepthWriteMask = All;
	StencilEnable = False;
};

DepthStencilState DepthWriteStencil
{
	DepthEnable = True;
    DepthWriteMask = All;
    DepthFunc = Always;

	StencilEnable = True;

	FrontFaceStencilFunc  = Greater;
	FrontFaceStencilPass = Incr;
	BackFaceStencilFunc  = Greater;
	BackFaceStencilPass = Incr;
};

DepthStencilState DepthTest
{
	DepthEnable = True;
    DepthFunc = Less;
    DepthWriteMask = Zero;
	StencilEnable = False;
};

DepthStencilState DepthDisable
{
	DepthEnable = False;
    StencilEnable = False;
};

RasterizerState DisableCulling 
{ 
	CullMode = None; 
};

//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
Texture3D g_volumeTexture : register(t0);        // Color texture for mesh
Texture3D g_volumeTextureNorm : register(t1);
StructuredBuffer<VS_INPUT> g_sbTriangles : register(t2);
StructuredBuffer<TriData> g_sbSortedTriangles : register(t3);

static const float g_fDifLightC = 0.05;
static const float g_fAmbientLightC = 0.95;

cbuffer FrameConstants: register(b0)
{
	float3 g_vLightColor : packoffset(c0) = {1.f, 1.f, 0.3f};
	float3 g_vLightDir : packoffset(c1) = {0.577f, 0.577f, -0.577f} ;
	uint  g_nFrameWidth : packoffset(c0.w);
	uint  g_nFrameHeight : packoffset(c1.w);
};
 
PS_INPUT VS_DrawSlices(uint vId:SV_VertexID)
{
	PS_INPUT res;
	uint triIndex = g_sbSortedTriangles[vId / 3].triInd;
	VS_INPUT v = g_sbTriangles[ 3*triIndex + (vId % 3) ];
	
	res.pos = v.pos;
	res.tex = v.tex;
	
	return res;
}

void PS_DrawDepth( PS_INPUT input )
{
	float4 res = g_volumeTexture.Sample(samPoint, input.tex);
	if (res.a < 0.03125f)
		discard;
}

[earlydepthstencil] float4 PS_DrawSlices( PS_INPUT input ) : SV_Target
{
	float4 res = g_volumeTexture.Sample(samLinear, input.tex);
	if (res.a < 0.03125f)
		discard;

// 	res.rgb*=res.a;
// 	return res;

	float3 norm;
	norm.xyz = g_volumeTextureNorm.Sample(samLinear, input.tex);
	norm.z = sqrt(1.f - norm.x*norm.x - norm.y*norm.y);

 	float3 diffClr = saturate(dot(norm, g_vLightDir))*g_vLightColor;
	res.rgb = res.rgb*g_fAmbientLightC + diffClr*g_fDifLightC;
//	res.rgb = norm;
	res.rgb *= res.a;

	return float4(res.rgb, res.a);
}

float4 PS_DrawPrism( PS_INPUT input ) : SV_Target
{
    return float4(1.f, 1.f, 1.f, 0.05f);
}


//--------------------------------------------------------------------------------------
// Techniques
//--------------------------------------------------------------------------------------

technique10 DrawSlices
{
    pass P0
    {
		SetBlendState(AlphaBlendDisable, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
        SetVertexShader( CompileShader( vs_5_0, VS_DrawSlices() ) );
        SetGeometryShader(NULL);
        SetPixelShader( CompileShader( ps_5_0, PS_DrawDepth() ) );
		SetDepthStencilState(DepthWriteStencil, 8);
    }
	pass P1
    {
		SetRasterizerState(DisableCulling);
		SetBlendState(BackToFrontAlphaBlend, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
        SetVertexShader( CompileShader( vs_5_0, VS_DrawSlices() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_5_0, PS_DrawSlices() ) );
		SetDepthStencilState(DepthTest, 0);
    }
}

technique10 DebugDrawPrism
{
	pass P0
    {
		SetRasterizerState(DisableCulling);
		SetBlendState(BackToFrontAlphaBlend, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
        SetVertexShader( CompileShader( vs_5_0, VS_DrawSlices() ) );
        SetGeometryShader( NULL );
        SetPixelShader( CompileShader( ps_5_0, PS_DrawPrism() ) );
		SetDepthStencilState(DepthDisable, 0);
    }
}

